import os
if os.name == 'nt':  # Windows系统
    import ctypes
    import winreg
    # 设置 DPI 感知
    try:
        ctypes.windll.user32.SetProcessDPIAware()
    except:
        pass

import sys
import json
import threading
import time
import qrcode
from PIL import Image
from io import BytesIO
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import pyautogui
import socket
from PySide6.QtWidgets import QApplication, QSystemTrayIcon, QMenu, QWidget, QVBoxLayout, QPushButton, QLabel, QLineEdit, QMessageBox
from PySide6.QtGui import QIcon, QPixmap
from PySide6.QtCore import Qt, QCoreApplication, QTimer
from PySide6.QtWidgets import QStyle
import struct
import subprocess
import platform
import psutil

# 设置 DPI 策略
QApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)

# 初始化Qt应用
qt_app = QApplication(sys.argv)

# 初始化Flask应用
app = Flask(__name__)
socketio = SocketIO(app)

def add_firewall_rule():
    """添加Windows防火墙规则"""
    try:
        # 获取当前程序路径
        if getattr(sys, 'frozen', False):
            # 如果是打包后的exe
            exe_path = os.path.abspath(sys.executable)
        else:
            # 如果是Python脚本
            exe_path = os.path.abspath(sys.argv[0])

        # 使用管理员权限运行命令
        commands = [
            # 删除可能存在的旧规则
            ['netsh', 'advfirewall', 'firewall', 'delete', 'rule', 'name="PC遥控器"'],
            # 添加新的入站规则
            ['netsh', 'advfirewall', 'firewall', 'add', 'rule',
             'name="PC遥控器"',
             'dir=in',
             'action=allow',
             f'program="{exe_path}"',
             'enable=yes',
             'profile=any',
             'protocol=TCP',
             'localport=5000']
        ]
        
        for cmd in commands:
            subprocess.run(cmd, shell=True, capture_output=True)
            
    except Exception as e:
        print(f"添加防火墙规则失败: {e}")

def add_to_startup():
    """添加程序到开机自启动"""
    try:
        # 获取程序路径
        if getattr(sys, 'frozen', False):
            # 如果是打包后的exe
            app_path = os.path.abspath(sys.executable)
        else:
            # 如果是Python脚本
            app_path = os.path.abspath(sys.argv[0])
            
        # 打开注册表键
        key = winreg.OpenKey(
            winreg.HKEY_CURRENT_USER,
            r"Software\Microsoft\Windows\CurrentVersion\Run",
            0,
            winreg.KEY_SET_VALUE
        )
        
        # 设置注册表项
        winreg.SetValueEx(key, "PC遥控器", 0, winreg.REG_SZ, f'"{app_path}"')
        winreg.CloseKey(key)
        return True
    except Exception as e:
        print(f"添加开机自启动失败: {e}")
        return False

def remove_from_startup():
    """从开机自启动中移除程序"""
    try:
        # 打开注册表键
        key = winreg.OpenKey(
            winreg.HKEY_CURRENT_USER,
            r"Software\Microsoft\Windows\CurrentVersion\Run",
            0,
            winreg.KEY_SET_VALUE
        )
        
        # 删除注册表项
        winreg.DeleteValue(key, "PC遥控器")
        winreg.CloseKey(key)
        return True
    except Exception as e:
        print(f"移除开机自启动失败: {e}")
        return False

def is_in_startup():
    """检查程序是否在开机自启动中"""
    try:
        # 打开注册表键
        key = winreg.OpenKey(
            winreg.HKEY_CURRENT_USER,
            r"Software\Microsoft\Windows\CurrentVersion\Run",
            0,
            winreg.KEY_READ
        )
        
        try:
            # 尝试读取注册表项
            winreg.QueryValueEx(key, "PC遥控器")
            winreg.CloseKey(key)
            return True
        except:
            winreg.CloseKey(key)
            return False
    except Exception as e:
        print(f"检查开机自启动状态失败: {e}")
        return False

class SystemTray(QSystemTrayIcon):
    def __init__(self):
        super().__init__()
        # 使用自定义图标
        icon = QIcon("icon.ico")  # 使用自定义图标
        self.setIcon(icon)
        self.setToolTip('PC遥控器')
        
        # 创建托盘菜单
        self.menu = QMenu()
        
        # 添加菜单项
        show_action = self.menu.addAction("显示设置")
        show_action.triggered.connect(self.show_settings)
        
        startup_action = self.menu.addAction("开机自启动")
        startup_action.setCheckable(True)
        startup_action.setChecked(is_in_startup())
        startup_action.triggered.connect(self.toggle_startup)
        
        quit_action = self.menu.addAction("退出")
        quit_action.triggered.connect(self.quit_app)
        
        self.setContextMenu(self.menu)
        
        # 创建设置窗口
        self.settings_window = SettingsWindow()
        # 设置窗口图标
        self.settings_window.setWindowIcon(icon)  # 使用相同的自定义图标
        # 显示设置窗口
        self.settings_window.show()
        
        # 添加防火墙规则
        add_firewall_rule()
    
    def show_settings(self):
        if not self.settings_window:
            self.settings_window = SettingsWindow()
            # 设置窗口图标
            icon = QIcon("icon.ico")  # 使用自定义图标
            self.settings_window.setWindowIcon(icon)
        self.settings_window.show()
    
    def toggle_startup(self, checked):
        """切换开机自启动状态"""
        if checked:
            if add_to_startup():
                print("已添加到开机自启动")
            else:
                print("添加开机自启动失败")
        else:
            if remove_from_startup():
                print("已从开机自启动移除")
            else:
                print("移除开机自启动失败")
    
    def quit_app(self):
        QApplication.quit()

class SettingsWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PC遥控器设置")
        self.setFixedSize(300, 250)  # 增加窗口高度以容纳二维码
        
        # 设置窗口样式
        self.setStyleSheet("""
            QWidget {
                background-color: #2a2a2a;
                color: white;
            }
            QPushButton {
                background-color: #444444;
                border: none;
                padding: 10px;
                border-radius: 5px;
                color: white;
            }
            QPushButton:hover {
                background-color: #555555;
            }
            QLabel {
                color: white;
            }
        """)
        
        # 创建布局
        layout = QVBoxLayout()
        
        # 添加标题
        title = QLabel("PC遥控器设置-Senmoya出品")
        title.setStyleSheet("font-size: 16px; font-weight: bold;")
        title.setAlignment(Qt.AlignCenter)
        layout.addWidget(title)
        
        # 添加状态信息
        status = QLabel("状态：正在运行")
        status.setAlignment(Qt.AlignCenter)
        layout.addWidget(status)
        
        # 添加IP地址信息
        ip = QLabel(f"访问地址：http://{get_local_ip()}:5000")
        ip.setAlignment(Qt.AlignCenter)
        layout.addWidget(ip)
        
        # 生成并显示二维码
        qr = qrcode.QRCode(
            version=1,
            error_correction=qrcode.constants.ERROR_CORRECT_L,
            box_size=10,
            border=4,
        )
        url = f"http://{get_local_ip()}:5000"
        qr.add_data(url)
        qr.make(fit=True)
        
        # 创建二维码图片
        qr_image = qr.make_image(fill_color="white", back_color="black")
        
        # 将PIL图片转换为QPixmap
        buffer = BytesIO()
        qr_image.save(buffer, format='PNG')
        qr_pixmap = QPixmap()
        qr_pixmap.loadFromData(buffer.getvalue())
        
        # 创建并设置二维码标签
        qr_label = QLabel()
        qr_label.setPixmap(qr_pixmap.scaled(200, 200, Qt.KeepAspectRatio, Qt.SmoothTransformation))
        qr_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(qr_label)
        
        self.setLayout(layout)

def get_local_ip():
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s.connect(("8.8.8.8", 80))
        ip = s.getsockname()[0]
        s.close()
        return ip
    except:
        return "127.0.0.1"

# Flask路由和事件处理
@app.route('/')
def index():
    return render_template('index.html')

@socketio.on('connect')
def handle_connect():
    print('客户端已连接')

@socketio.on('disconnect')
def handle_disconnect():
    print('客户端已断开')

@socketio.on('mouse_move')
def handle_mouse_move(data):
    try:
        # 确保data是字典类型
        if isinstance(data, dict):
            x = data.get('x')
            y = data.get('y')
            if x is not None and y is not None:
                try:
                    # 设置更快的移动速度
                    pyautogui.MINIMUM_DURATION = 0  # 移除延迟
                    pyautogui.MINIMUM_SLEEP = 0     # 移除睡眠时间
                    pyautogui.PAUSE = 0             # 移除暂停
                    
                    x = int(float(x))  # 处理可能的浮点数
                    y = int(float(y))  # 处理可能的浮点数
                    
                    # 使用相对移动
                    pyautogui.moveRel(x, y, duration=0)
                except (ValueError, TypeError) as e:
                    print(f"坐标转换失败: {e}")
            else:
                print("缺少坐标数据")
        else:
            print(f"数据格式错误: {data}")
    except Exception as e:
        print(f"移动鼠标失败: {e}")

@socketio.on('mouse_click')
def handle_mouse_click(data):
    try:
        button = data.get('button', 'left')
        if button == 'right':
            pyautogui.rightClick()
        elif button == 'double':
            pyautogui.doubleClick()
        else:
            pyautogui.click()
    except Exception as e:
        print(f"点击失败: {e}")

@socketio.on('key_press')
def handle_key_press(data):
    try:
        key = data['key']
        if key == 'volume_up':
            for _ in range(5):
                pyautogui.press('volumeup')
        elif key == 'volume_down':
            for _ in range(5):
                pyautogui.press('volumedown')
        elif key == 'volume_mute':
            pyautogui.press('volumemute')
        elif key == 'media_play_pause':
            # 尝试多种播放/暂停快捷键
            try:
                pyautogui.press('playpause')
            except:
                pyautogui.press('space')  # 空格键作为备选
        elif key == 'media_next':
            # 尝试多种下一集快捷键
            try:
                # 同时发送B站和YouTube的快捷键
                pyautogui.press(']')  # B站快捷键
                time.sleep(0.1)  # 短暂延迟
                pyautogui.press('nexttrack')  # YouTube快捷键
            except:
                try:
                    pyautogui.hotkey('shift', 'n')
                except:
                    pyautogui.press('right')
        elif key == 'media_previous':
            # 尝试多种上一集快捷键
            try:
                # 同时发送B站和YouTube的快捷键
                pyautogui.press('[')  # B站快捷键
                time.sleep(0.1)  # 短暂延迟
                pyautogui.press('prevtrack')  # YouTube快捷键
            except:
                try:
                    pyautogui.hotkey('shift', 'p')
                except:
                    pyautogui.press('left')
        elif key == 'seek_forward':
            pyautogui.hotkey('right')  # 使用右箭头键快进
        elif key == 'seek_backward':
            pyautogui.hotkey('left')   # 使用左箭头键后退
        elif key == 'sleep':
            os.system('rundll32.exe powrprof.dll,SetSuspendState 0,1,0')
        elif key == 'enter':
            pyautogui.press('enter')
        elif key == 'backspace':
            pyautogui.press('backspace')
        elif key == 'space':
            pyautogui.press('space')
        elif key == 'tab':
            pyautogui.press('tab')
        elif key == 'shift':
            pyautogui.keyDown('shift')
            pyautogui.keyUp('shift')
        elif key == 'ctrl':
            pyautogui.keyDown('ctrl')
            pyautogui.keyUp('ctrl')
        elif key == 'alt':
            pyautogui.keyDown('alt')
            pyautogui.keyUp('alt')
        elif key == 'win':
            pyautogui.press('win')
        elif key == 'esc':
            pyautogui.press('esc')
        elif key == 'delete':
            pyautogui.press('delete')
        elif key == 'home':
            pyautogui.press('home')
        elif key == 'end':
            pyautogui.press('end')
        elif key == 'pageup':
            pyautogui.press('pageup')
        elif key == 'pagedown':
            pyautogui.press('pagedown')
        elif key == 'up':
            pyautogui.press('up')
        elif key == 'down':
            pyautogui.press('down')
        elif key == 'left':
            pyautogui.press('left')
        elif key == 'right':
            pyautogui.press('right')
        elif key == '.':
            pyautogui.write('.')
        elif key.startswith('text:'):
            # 处理文本输入
            text = key[5:]  # 移除 'text:' 前缀
            pyautogui.write(text)
    except Exception as e:
        print(f"按键失败: {e}")

def run_flask():
    try:
        socketio.run(app, host='0.0.0.0', port=5000, debug=False)
    except Exception as e:
        print(f"Flask服务器启动失败: {e}")

if __name__ == '__main__':
    # 创建系统托盘图标
    tray = SystemTray()
    
    # 在新线程中运行Flask服务器
    flask_thread = threading.Thread(target=run_flask)
    flask_thread.daemon = True
    flask_thread.start()
    
    # 显示系统托盘图标
    tray.show()
    
    # 启动应用程序
    sys.exit(qt_app.exec()) 
